# Cross-platform and multi-configuration build of the Methane Kit

name: '🏗️ CI Build'

on:
  push:
    branches: [ master, develop ]
    paths:
    - '.github/workflows/ci-build.yml'
    - 'Apps/**'
    - 'Modules/**'
    - 'Tests/**'
    - 'Externals/**'
    - 'CMake/**'
    - 'Build/*/CI/**'
    - 'CMakeLists.txt'
    - 'CMakePresets.json'
  pull_request:
    branches: [ master ]
    paths:
    - '.github/workflows/ci-build.yml'
    - 'Apps/**'
    - 'Modules/**'
    - 'Tests/**'
    - 'Externals/**'
    - 'CMake/**'
    - 'Build/*/CI/**'
    - 'CMakeLists.txt'
    - 'CMakePresets.json'
  schedule:
    - cron: '20 23 * * 3'  # Scheduled workflow will not run in GitHub forks by default

env:
  METHANE_VERSION_MAJOR: 0
  METHANE_VERSION_MINOR: 7
  METHANE_VERSION_PATCH: 3
  METHANE_VERSION_BUILD: ${{ github.run_number }}
  TRACY_RELEASE_VERSION: "0.9.1"
  VULKAN_SDK_VERSION: "1.3.250.1"
  ORIGIN_REPOSITORY: 'MethanePowered/MethaneKit'

jobs:
  build:
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: windows-latest
            name: "Win64_DX_Release"
            config_preset: "VS2022-Win64-DX-Default"
            build_preset: "VS2022-Win64-DX-Release"
            named_logo: Windows
            run_tests: true
            add_tracy_app: false
            install_vulkan_sdk: false

          - os: windows-latest
            name: "Win64_VK_Release"
            config_preset: "VS2022-Win64-VK-Default"
            build_preset: "VS2022-Win64-VK-Release"
            named_logo: Windows
            run_tests: true
            add_tracy_app: false
            install_vulkan_sdk: false

          - os: windows-latest
            name: "Win64_DX_Profile"
            config_preset: "VS2022-Win64-DX-Profile"
            build_preset: "VS2022-Win64-DX-Profile"
            named_logo: Windows
            run_tests: false
            add_tracy_app: true
            install_vulkan_sdk: false

          - os: windows-latest
            name: "Win64_VK_Profile"
            config_preset: "VS2022-Win64-VK-Profile"
            build_preset: "VS2022-Win64-VK-Profile"
            named_logo: Windows
            run_tests: false
            add_tracy_app: true
            install_vulkan_sdk: false

          - os: windows-latest
            name: "Win32_DX_Release"
            config_preset: "VS2022-Win32-DX-Default"
            build_preset: "VS2022-Win32-DX-Release"
            named_logo: Windows
            run_tests: true
            add_tracy_app: false
            install_vulkan_sdk: false

          - os: windows-latest
            name: "Win32_VK_Release"
            config_preset: "VS2022-Win32-VK-Default"
            build_preset: "VS2022-Win32-VK-Release"
            named_logo: Windows
            run_tests: true
            add_tracy_app: false
            install_vulkan_sdk: false

          - os: windows-latest
            name: "Win32_DX_Profile"
            config_preset: "VS2022-Win32-DX-Profile"
            build_preset: "VS2022-Win32-DX-Profile"
            named_logo: Windows
            run_tests: false
            add_tracy_app: true
            install_vulkan_sdk: false

          - os: windows-latest
            name: "Win32_VK_Profile"
            config_preset: "VS2022-Win32-VK-Profile"
            build_preset: "VS2022-Win32-VK-Profile"
            named_logo: Windows
            run_tests: false
            add_tracy_app: true
            install_vulkan_sdk: false

          - os: ubuntu-latest
            name: "Ubuntu_VK_Release"
            config_preset: "Make-Lin-VK-Release"
            build_preset: "Make-Lin-VK-Release"
            named_logo: Linux
            run_tests: true
            add_tracy_app: false
            install_vulkan_sdk: false

          - os: ubuntu-latest
            name: "Ubuntu_VK_Profile"
            config_preset: "Make-Lin-VK-Profile"
            build_preset: "Make-Lin-VK-Profile"
            named_logo: Linux
            run_tests: false
            add_tracy_app: true
            install_vulkan_sdk: false

          - os: macos-latest
            name: "MacOS_VK_Release"
            config_preset: "Xcode-Mac-VK-Default"
            build_preset: "Xcode-Mac-VK-Release"
            named_logo: Apple
            run_tests: true
            add_tracy_app: false
            install_vulkan_sdk: true

          - os: macos-latest
            name: "MacOS_MTL_Release"
            config_preset: "Xcode-Mac-MTL-Default"
            build_preset: "Xcode-Mac-MTL-Release"
            named_logo: Apple
            run_tests: true
            add_tracy_app: false
            install_vulkan_sdk: false

          - os: macos-latest
            name: "MacOS_MTL_Profile"
            config_preset: "Xcode-Mac-MTL-Profile"
            build_preset: "Xcode-Mac-MTL-Profile"
            named_logo: Apple
            run_tests: false
            add_tracy_app: true
            install_vulkan_sdk: false

          - os: macos-latest
            name: "iOS_Sim_MTL_Release"
            config_preset: "Xcode-iOS-Sim-MTL-Default"
            build_preset: "Xcode-iOS-Sim-MTL-Release"
            named_logo: Apple
            run_tests: false
            add_tracy_app: false
            install_vulkan_sdk: false

          - os: macos-latest
            name: "tvOS_Sim_MTL_Release"
            config_preset: "Xcode-tvOS-Sim-MTL-Default"
            build_preset: "Xcode-tvOS-Sim-MTL-Release"
            named_logo: Apple
            run_tests: false
            add_tracy_app: false
            install_vulkan_sdk: false

    name: ${{ matrix.name }}
    runs-on: ${{ matrix.os }}

    env:
      INSTALL_DIR: Build/Output/${{ matrix.config_preset }}/Install
      BUILD_LOG_FILE: Build/Output/${{ matrix.config_preset }}/Install/Build.log

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3
        with:
          fetch-depth: 0

      - name: Install Linux prerequisites
        if: ${{ runner.os == 'Linux' }}
        run: ./Build/Unix/CI/InstallLinuxPrerequisites.sh

      - name: Install TestSpace
        if: ${{ github.repository == env.ORIGIN_REPOSITORY }}
        uses: testspace-com/setup-testspace@v1
        with:
          domain: ${{ github.repository_owner }}

      - name: Install Vulkan SDK ${{ env.VULKAN_SDK_VERSION }}
        if: ${{ matrix.install_vulkan_sdk }}
        run: ./Build/Unix/CI/InstallVulkanSdk.sh "${{ env.VULKAN_SDK_VERSION }}" "${{ runner.tool_cache }}/VulkanSDK"

      - name: Initialize Externals Cache
        uses: actions/cache@v3
        with:
          path: Build/Output/ExternalsCache
          key: ExternalsCache-${{ matrix.config_preset }}-${{ hashFiles('Externals/*.cmake') }}

      - name: CMake Configure Preset ${{ matrix.config_preset }}
        shell: bash
        run: ./Build/Unix/CI/CMakeConfigurePreset.sh "${{ matrix.config_preset }}"

      - name: CMake Build Preset ${{ matrix.build_preset }}
        shell: bash
        run: ./Build/Unix/CI/CMakeBuildPreset.sh "${{ matrix.build_preset }}"

      - name: Run Unit-Tests on Unix
        if: ${{ matrix.run_tests && runner.os != 'Windows'}}
        working-directory: ${{ env.INSTALL_DIR }}/Tests
        shell: bash
        run: ${{ github.workspace }}/Build/Unix/CI/RunUnitTests.sh junit

      - name: Run Unit-Tests on Windows
        if: ${{ matrix.run_tests && runner.os == 'Windows' }}
        working-directory: ${{ env.INSTALL_DIR }}/Tests
        shell: cmd
        run: ${{ github.workspace }}\Build\Windows\CI\RunUnitTests.bat junit

      - name: Upload Test Results Artifact
        uses: actions/upload-artifact@v3
        if: ${{ matrix.run_tests && (success() || failure()) }}
        with:
          name: MethaneKit_${{ matrix.name }}_TestResults_${{ env.METHANE_VERSION_MAJOR }}.${{ env.METHANE_VERSION_MINOR }}.${{ env.METHANE_VERSION_PATCH }}.${{ env.METHANE_VERSION_BUILD }}
          path: ${{ env.INSTALL_DIR }}/Tests/Results/junit/*.xml

      - name: Upload Test Results and Build Log to TestSpace server
        if: ${{ github.repository == env.ORIGIN_REPOSITORY && matrix.run_tests && (success() || failure()) }}
        continue-on-error: true # testspace will fail if test result already exists for current build id, but it's OK on build re-run.
        shell: bash
        run: |
          testspace \
            "[ ${{ matrix.name }} ]${{ env.INSTALL_DIR }}/Tests/Results/junit/*.xml" \
            "[ ${{ matrix.name }} ]${{ env.BUILD_LOG_FILE }}"

      - name: Add README and Build-Info files
        if: ${{ success() || failure() }}
        shell: bash
        env:
          REPO_URL: ${{ github.repositoryUrl }}
          BRANCH_NAME: ${{ github.ref_name }}
          COMMIT_SHA: ${{ github.sha }}
          RUN_ID: ${{ github.run_id }}
          CONFIG_PRESET: ${{ matrix.config_preset }}
          BUILD_PRESET: ${{ matrix.build_preset }}
          RUNNER_INFO: "${{ runner.name }}, ${{ runner.os }}, ${{ runner.arch }}"
        run: |
          cp README.md $INSTALL_DIR/README.md
          ./Build/Unix/CI/WriteBuildInfo.sh "$INSTALL_DIR/Build-Info.txt"            

      - name: Download Tracy release
        if: ${{ matrix.add_tracy_app && (success() || failure()) }}
        shell: bash
        run: ./Build/Unix/CI/DownloadTracyRelease.sh "${{ env.TRACY_RELEASE_VERSION }}" "$INSTALL_DIR/Apps"

      - name: Archive Build Artifacts
        if: ${{ success() || failure() }}
        shell: bash
        working-directory: ${{ env.INSTALL_DIR }}
        run: 7z a -t7z -mx=9 MethaneKit_${{ matrix.name }}.7z *

      - name: Upload Archived Build Artifacts
        if: ${{ success() || failure() }}
        uses: actions/upload-artifact@v3
        with:
          name: MethaneKit_${{ matrix.name }}_${{ env.METHANE_VERSION_MAJOR }}.${{ env.METHANE_VERSION_MINOR }}.${{ env.METHANE_VERSION_PATCH }}.${{ env.METHANE_VERSION_BUILD }}
          path: ${{ env.INSTALL_DIR }}/MethaneKit_${{ matrix.name }}.7z

      - name: Update Badge Parameters
        id: badge-params
        if: ${{ github.repository == env.ORIGIN_REPOSITORY && github.event_name != 'pull_request' && always() }}
        shell: bash
        run: ./Build/Unix/CI/UpdateBadgeParameters.sh "${{ job.status }}"

      - name: Update Badge JSON
        if: ${{ github.repository == env.ORIGIN_REPOSITORY && github.event_name != 'pull_request' && always() }}
        uses: schneegans/dynamic-badges-action@v1.6.0
        with:
          auth: ${{ secrets.GIST_TOKEN }}
          gistID: 96d788046ccd52b45b3354a99f8569c3
          filename: MethaneKit_${{ matrix.name }}_${{ github.ref_name }}.json
          namedLogo: ${{ matrix.named_logo }} # https://simpleicons.org
          label: ${{ matrix.name }}
          labelColor: #f5f5f5
          logoColor: #f5f5f5
          message: ${{ env.badge_message }}
          color: ${{ env.badge_color }}

      - name: Windows disk space report
        if: ${{ runner.os == 'Windows' && always() }}
        run: Get-PSDrive

  event_file:
    name: "Event File"
    runs-on: ubuntu-latest
    steps:
      - name: Upload Event File
        uses: actions/upload-artifact@v3
        with:
          name: EventFile
          path: ${{ github.event_path }}